package IC.Analyzer.Types;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import IC.AST.nodes.ClassDecl;

public class ClassType extends RefType {
	private ClassDecl decl;
	private ClassType baseClassType;
	private static Map<ClassDecl, ClassType> cache;

	/**
	 * @return the baseClassType
	 */
	public ClassType getBaseClassType() {
		return baseClassType;
	}

	/**
	 * @return the decl
	 */
	public ClassDecl getDecl() {
		return decl;
	}

	/**
	 * @param decl
	 * @return create a new class type or return a pointer to already
	 *         existing one
	 */
	public static ClassType getIt(ClassDecl decl, ClassType baseClassType) {
		if (cache == null)
			cache = new HashMap<ClassDecl, ClassType>();
		ClassType ret = cache.get(decl);
		if (ret == null) {
			ret = new ClassType(decl, baseClassType);
			cache.put(decl, ret);
		}
		return ret;
	}

	private ClassType(ClassDecl decl, ClassType baseClassType) {
		this.decl = decl;
		this.baseClassType = baseClassType;
	}

	public boolean isSubtypeOf(Type t) {
		return (this == t)
		|| ((baseClassType != null) && baseClassType.isSubtypeOf(t));
	}
	/*
    public String toString() {
	return "class " + decl.getClassID();
    }
	 */

	public String toString() {
		String base = "";
		if(baseClassType != null) {
			base = ", base: "+ baseClassType;
		}
		return "class " + decl.getClassID() + base+ " ";
	}

	/**
	 * 
	 * @return a string represantation of all method types
	 */
	public static String toStringAll() {
		StringBuffer s = new StringBuffer();

		Set<Entry<ClassDecl, ClassType>> set = cache.entrySet();

		for (Entry<ClassDecl, ClassType> e : set) {
			s.append(e.getValue());
			s.append("\n");
		}

		return s.toString();
	}
}
